﻿using System.Collections.Generic;
using System.Linq;
using GISCore.Geometry;
using GISCore.Geometry.Intersectors;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace GISUnitTests
{
    
    
    /// <summary>
    ///This is a test class for SweepLineTest and is intended
    ///to contain all SweepLineTest Unit Tests
    ///</summary>
    [TestClass()]
    public class SweepLineTest
    {


        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion


        /// <summary>
        ///A test for SweepLine Constructor
        ///</summary>
        [TestMethod()]
        public void SweepLineConstructorTest()
        {
            SweepLine target = new SweepLine();
            Assert.IsTrue(true);
        }

        /// <summary>
        ///A test for Intersect
        ///</summary>
        [TestMethod()]
        public void IntersectTest()
        {
            SweepLine target = new SweepLine();
            #region Setup Test1
            Point pa = new Point(2, 4);
            Point pd = new Point(4, 6);
            Point pc = new Point(6, 4);
            Point pb = new Point(4, 2);
            Point p4 = new Point(4, 3);
            Point p3 = new Point(7, 6);
            Point p2 = new Point(9, 4);
            Point p1 = new Point(7, 2);

            Line lad = new Line(pa, pd);
            Line ldc = new Line(pd, pc);
            Line lcb = new Line(pc, pb);
            Line lba = new Line(pb, pa);
            Line l43 = new Line(p4, p3);
            Line l32 = new Line(p3, p2);
            Line l21 = new Line(p2, p1);
            Line l14 = new Line(p1, p4);

            lad.next = ldc;
            lad.prev = lba;
            ldc.next = lcb;
            ldc.prev = lad;
            lcb.next = lba;
            lcb.prev = ldc;
            lba.next = lad;
            lba.prev = lcb;

            l43.next = l32;
            l43.prev = l14;
            l32.next = l21;
            l32.prev = l43;
            l21.next = l14;
            l21.prev = l32;
            l14.next = l43;
            l14.prev = l21;

            List<Line> l1 = new List<Line>();
            l1.Add(lad);
            l1.Add(ldc);
            l1.Add(lcb);
            l1.Add(lba);
            Polygon poly1 = new Polygon(1, l1);

            List<Line> l2 = new List<Line>();
            l2.Add(l43);
            l2.Add(l32);
            l2.Add(l21);
            l2.Add(l14);
            Polygon poly2 = new Polygon(2, l2);
            var lines = new List<Line>();
            lines.AddRange(l1);
            lines.AddRange(l2);
            #endregion

            var actual = target.Intersect(lines).ToList();
            var expected = new List<Point>() { new Point(5.5, 4.5), new Point(4.75, 2.75) };
            Assert.AreEqual(actual.Count, expected.Count);
            Assert.AreEqual(actual[0], expected[0]);
            Assert.AreEqual(actual[1], expected[1]);

            #region Setup Test 2
            pa = new Point(1, 1);
            pb = new Point(5, 1);
            pc = new Point(2.5, 5);

            p3 = new Point(1, 4);
            p2 = new Point(5, 4);
            p1 = new Point(2.5, 0);

            Line lab = new Line(pa, pb);
            Line lac = new Line(pa, pc);
            Line lbc = new Line(pc, pb);

            l32 = new Line(p3, p2);
            l21 = new Line(p2, p1);
            Line l13 = new Line(p1, p3);

            l1 = new List<Line>() { lab, lac, lbc };
            poly1 = new Polygon(1, l1);

            l2 = new List<Line>() { l32, l21, l13 };
            poly2 = new Polygon(2, l2);
            lines = new List<Line>();
            lines.AddRange(l1);
            lines.AddRange(l2);
            #endregion

            actual = target.Intersect(lines).ToList();
            expected = new List<Point>() { new Point(2.125, 4), new Point(1.5625, 2.5), new Point(3.125, 4),
                new Point(4.0625, 2.5), new Point(3.125, 1), new Point(2.125, 1) };
            expected.Sort();
            actual.Sort();
            Assert.AreEqual(actual.Count, expected.Count);
            Assert.AreEqual(actual[0], expected[0]);
            Assert.AreEqual(actual[1], expected[1]);
            Assert.AreEqual(actual[2], expected[2]);
            Assert.AreEqual(actual[3], expected[3]);
            Assert.AreEqual(actual[4], expected[4]);
            Assert.AreEqual(actual[5], expected[5]);
        }
    }
}
